Skip to content

fix(mobile): make Bluetooth survive iOS Guided Access (kiosk lock)#39

Merged
burkben merged 1 commit into
mainfrom
burkben-fix-guided-access-speedometer
Jun 24, 2026
Merged

fix(mobile): make Bluetooth survive iOS Guided Access (kiosk lock)#39
burkben merged 1 commit into
mainfrom
burkben-fix-guided-access-speedometer

Conversation

@burkben

@burkben burkben commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Bug report

Using the app, the speedometer registered nothing. Turned out Guided Access was on. Turning Guided Access off made it work again — but then I was completely locked out of starting Guided Access, with iOS showing an error.

Root cause

All three symptoms trace to one iOS conflict: CoreBluetooth's system Bluetooth dialog vs. Guided Access.

  • iOS suppresses system dialogs while a Guided Access session is active, and conversely a pending system Bluetooth dialog blocks Guided Access from starting.
  • react-native-ble-plx shows iOS's system Bluetooth permission/power alert when BT is off or not-yet-authorized. That single modal explains everything:
    1. Scanning under Guided Access → the system BT alert is suppressed → portal never connects, gauge is dead.
    2. Turning Guided Access off → the alert can finally resolve → works again.
    3. The lingering system BT alert → blocks Guided Access from starting → the iOS error.

react-native-ble-plx@3.5.1 exposes no JS option to suppress that alert (CBCentralManagerOptionShowPowerAlertKey isn't surfaced), so this is fixed in-app + docs, with no native patch.

Changes

Mobile

  • ble/bleStatus.ts (+ unit tests) — pure BlePhase → banner mapping for poweredOff / unauthorized / unsupported / error.
  • components/BleStatusBanner.tsx — renders that banner on the home speedometer screen, with an Open Settings shortcut for the permission case. Previously these states only showed on the Live-log screen, so under Guided Access the gauge sat silently dead with no explanation.
  • ble/blePortal.tsprewarmBle(), called from app/_layout.tsx at launch on a physical device, so the iOS Bluetooth permission/power prompts fire on the home screen — not mid-session inside Guided Access.

Docs

  • New docs/guides/ios-guided-access.md — kiosk setup (turn BT on + connect once before locking down) and troubleshooting for both the dead gauge and the "Guided Access could not be started" error.
  • Linked from README.md and docs/guides/ios-testflight.md.

Trade-off

The launch-time prewarm means a one-time Bluetooth permission prompt (and a "Bluetooth is off" alert, if applicable) now appears at app startup on a real device — intentional, to keep those prompts out of Guided Access sessions.

Validation

  • npm run typecheck — clean across workspaces.
  • npm test186 mobile + 49 protocol tests pass, including the new bleStatus tests.
  • No device build performed (CI-only environment); BLE/Guided-Access behavior is documented for on-device verification.

🤖 Generated with Copilot

Under iOS Guided Access, the speedometer registered nothing and users
could get locked out of starting Guided Access entirely. Root cause is a
single conflict: CoreBluetooth's system Bluetooth alert vs. Guided Access.
iOS suppresses system dialogs during a Guided Access session, and a
pending one blocks Guided Access from starting — so the portal never
connects (dead gauge), and the lingering modal jams Guided Access.

react-native-ble-plx 3.5.1 exposes no JS option to suppress that alert,
so this is fixed in-app + docs (no native patch):

- Surface BLE adapter problems (Bluetooth off / permission denied /
  unsupported / error) on the home speedometer screen via a new
  BleStatusBanner, with an Open Settings shortcut. Previously these only
  appeared on the Live-log screen, so the gauge sat silently dead.
- Add prewarmBle() and call it at launch (physical device only) so the
  iOS Bluetooth permission/power prompts fire on the home screen, not
  mid-session inside Guided Access.
- Pure bleStatus phase->banner mapping with unit tests.
- New docs/guides/ios-guided-access.md (kiosk setup + troubleshooting),
  linked from README and the TestFlight guide.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@burkben burkben merged commit 5ba15c4 into main Jun 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant